package com.passion.common.util;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.ISqlSegment;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import javax.validation.constraints.NotEmpty;
import java.util.List;
import java.util.function.Predicate;

/**
 * 建类说明：mybatis plus 工具类
 *
 * @author 中国印
 * @since 2023年03月05日 12:24:31
 */
@SuppressWarnings("unused")
public class MybatisPlusUtil {

    /**
     * 只返回 指定字段
     * 使用方式：
     * LambdaQueryWrapper<CreditPointRuleClass> queryWrapper = new LambdaQueryWrapper<>();
     * MybatisPlusUtil.fieldValues(fieldValues, queryWrapper, CreditPointRuleClass.class);
     */
    public static <T> void fieldValues(String fieldValues, LambdaQueryWrapper<T> queryWrapper, Class<T> clazz) {
        if (StringUtils.isNotBlank(fieldValues)) {
            Predicate<TableFieldInfo> predicate = null;
            String[] fieldValuesArray = fieldValues.split(",");
            for (String field : fieldValuesArray) {
                predicate = predicate == null ? p -> p.getColumn().equals(field) : predicate.or(p -> p.getColumn().equals(field));
            }
            queryWrapper.select(clazz, predicate);
        }
    }

    /**
     * @param queryWrapper {@link LambdaQueryWrapper}
     * @param column       排序字段
     * @param asc          是否升序
     * @param <T>          泛型
     */
    public static <T> void setOrderOne(LambdaQueryWrapper<T> queryWrapper, String column, boolean asc) {
        try {
            ISqlSegment[] sqlSegments = {SqlKeyword.ORDER_BY, () -> column, asc ? SqlKeyword.ASC : SqlKeyword.DESC};
            queryWrapper.getExpression().add(sqlSegments);
        } catch (Exception e) {
            throw new RuntimeException("设置排序出错：" + e.getMessage());
        }
    }

    /**
     * @param queryWrapper {@link LambdaQueryWrapper}
     * @param order        {@link OrderBy} 排序
     * @param <T>          泛型
     */
    public static <T> void setOrder(LambdaQueryWrapper<T> queryWrapper, OrderBy order) {
        setOrderOne(queryWrapper, order.getColumn(), order.isAsc());
    }

    /**
     * @param queryWrapper {@link LambdaQueryWrapper}
     * @param list         {@link OrderBy} 排序
     * @param <T>          泛型
     */
    public static <T> void setOrder(LambdaQueryWrapper<T> queryWrapper, List<OrderBy> list) {
        for (OrderBy order : list) {
            setOrder(queryWrapper, order);
        }
    }

    /**
     * @param queryWrapper {@link LambdaQueryWrapper}
     * @param orderItem    {@link OrderItem} 排序
     * @param <T>          泛型
     */
    public static <T> void setOrderItem(LambdaQueryWrapper<T> queryWrapper, OrderItem orderItem) {
        setOrderOne(queryWrapper, StrUtil.toUnderlineCase(orderItem.getColumn()), orderItem.isAsc());
    }

    /**
     * @param queryWrapper {@link LambdaQueryWrapper}
     * @param list         {@link OrderItem} 排序
     * @param <T>          泛型
     */
    public static <T> void setOrderItem(LambdaQueryWrapper<T> queryWrapper, List<OrderItem> list) {
        for (OrderItem order : list) {
            setOrderItem(queryWrapper, order);
        }
    }

    @Data
    public static class OrderBy {

        /**
         * 字段名称
         */
        @NotEmpty
        private String column;


        /**
         * 排序类型 升序：asc 降序：desc
         * 默认升序
         */
        private boolean asc = true;

        /**
         * 是否进行驼峰转下划线
         */
        private boolean toUnder = false;


        public String getColumn() {
            return isToUnder() ? StrUtil.toUnderlineCase(column) : column;
        }

        public String getColumn(boolean toUnder) {
            return toUnder ? StrUtil.toUnderlineCase(column) : column;
        }

        /**
         * 获取sql
         * @return 返回排序的sql语句片段
         */
        public String getSql(){
            return (isToUnder() ? StrUtil.toUnderlineCase(column) : column) + (this.isAsc()? " asc":" desc");
        }
    }
}

